#include "qmissionmanager.h"

#include "qmission.h"

#include <QVariant>

QMissionManager::QMissionManager(QObject *parent):
    QObject(parent),
    m_connect_test_mission(NULL),
    m_online(false),
    m_is_search(false)
{
}

QMissionManager::~QMissionManager()
{
    if(m_connect_test_mission!=NULL)
    {
        delete m_connect_test_mission;
    }
    clear();
}

void QMissionManager::set_search()
{
    m_is_search=true;
}

void QMissionManager::clear()
{
    qDeleteAll(m_missions);
    m_missions.clear();
    qDeleteAll(m_pause_list);
    m_pause_list.clear();
    qDeleteAll(m_delete_list);
    m_delete_list.clear();
    m_mission_group.clear();
}

void QMissionManager::add_mission(QMission *ms)
{
    QMission* mission=m_id_to_mission.value(ms->get_attribute(MISSION_UUID).toString());

    if(mission!=NULL)
    {
        *mission=*ms;
        if(m_delete_list.contains(mission))
        {
            m_delete_list.removeAll(mission);
            m_missions.append(mission);
        }
        else if(m_pause_list.contains(mission))
        {
            m_pause_list.removeAll(mission);
            m_missions.append(mission);
        }
        mission->ready();
        mission->set_attribute(MISSION_STATUS,MS_READY);
    }
    else
    {
        mission=new QMission((enMissionType)ms->get_attribute(MISSION_TYPE).toInt());
        *mission=*ms;
        mission->ready();
        m_id_to_mission.insert(mission->get_attribute(MISSION_UUID).toString(),mission);
        mission->set_attribute(MISSION_STATUS,MS_READY);
        m_missions.append(mission);
    }
}

void QMissionManager::remove_mission(const QString &id)
{
    QMission* ms=m_id_to_mission.value(id);

    if(ms!=NULL)
    {
        ms->set_attribute(MISSION_STATUS,MS_DELETE);
        m_missions.removeAll(ms);
        m_pause_list.removeAll(ms);
        m_mission_group.removeAll(ms);
        if(!m_delete_list.contains(ms))
        {
            m_delete_list.append(ms);
        }
    }
}

void QMissionManager::remove_mission(QMission *ms)
{
    remove_mission(ms->get_attribute(MISSION_UUID).toString());
}

QMission* QMissionManager::get_need_to_do()
{
    QMission *ms=NULL;
    int dis;
    int last_dis=0;

    if(m_missions.size()==0
            && m_connect_test_mission!=NULL
            && (m_connect_test_mission->need_to_do()
                                || m_connect_test_mission->get_attribute(MISSION_STATUS).toInt()==MS_RETRY))
    {
        return m_connect_test_mission;
    }

    foreach(QMission* m,m_missions)
    {
        if(m->get_attribute(MISSION_STATUS).toInt()==MS_RETRY)
        {
            return m;
        }
        dis=m->need_to_do();
        if(dis>0)
        {
            if(ms==NULL)
            {
                ms=m;
                last_dis=dis;
            }
            else
            {
                int level_m=m->get_attribute(MISSION_LEVEL).toInt();
                int level_ms=ms->get_attribute(MISSION_LEVEL).toInt();
                if(level_m<level_ms)
                {
                    ms=m;
                    last_dis=dis;
                }
                else if(level_m==level_ms)
                {
                    if(m->get_attribute(MISSION_TYPE).toInt()
                            <ms->get_attribute(MISSION_TYPE).toInt())
                    {
                        ms=m;
                        last_dis=dis;
                    }
                    else
                    {
                        if(last_dis<dis)
                        {
                            ms=m;
                            last_dis=dis;
                        }
                    }
                }
            }
        }
    }

    return ms;
}

QMission* QMissionManager::get_mission(const QString &id)
{
    if(m_connect_test_mission!=NULL && id==m_connect_test_mission->get_attribute(MISSION_UUID).toString())
    {
        return m_connect_test_mission;
    }
    return m_id_to_mission.value(id);
}

void QMissionManager::clear_delete(const QString &id)
{
    foreach(QMission* ms,m_delete_list)
    {
        if(ms->get_attribute(MISSION_UUID).toString()!=id)
        {
            m_id_to_mission.remove(ms->get_attribute(MISSION_UUID).toString());
            m_delete_list.removeAll(ms);
            delete ms;
        }
    }
}

void QMissionManager::mission_done(QMission *ms, int code)
{

    if(code!=0)
    {
        if(m_is_search || (code!=TIME_OUT_CODE && code!=TIME_OUT_CODE && code!=MISSION_ERROR))
        {
            emit mission_failed(ms,code);
        }
    }
    else
    {
        emit mission_success(ms);
    }

    if(m_is_search)
    {
        m_mission_group.removeAll(ms);
        remove_mission(ms);
        if(m_mission_group.size()!=0)
        {
            emit mission_group_progress(m_mission_group.size());
        }
        else
        {
            emit mission_group_end(true);
        }
        return;
    }

    if(code==TIME_OUT_CODE || code==CRC_ERROR_CODE || code==MISSION_ERROR)
    {
        int retry=ms->get_attribute(MISSION_RETRIES).toInt();
        retry--;
        ms->set_attribute(MISSION_RETRIES,retry);
        if(retry<=0)
        {
            m_connect_test_mission->ready();
            if(m_online)
            {
                m_online=false;
                emit offline();
                pause();
            }
        }
        else
        {
            ms->ready();
            if(m_connect_test_mission!=ms)
            {
                ms->set_attribute(MISSION_STATUS,MS_RETRY);
            }
        }
    }
    else if(code==0)
    {
        if(ms!=m_connect_test_mission)
        {
            if(m_mission_group.contains(ms))
            {
                m_mission_group.removeAll(ms);
                if(m_mission_group.size()!=0)
                {
                    emit mission_group_progress(m_mission_group.size());
                }
                else
                {
                    emit mission_group_end(true);
                }
            }
            if(ms->get_attribute(MISSION_TYPE).toInt()<=MT_TEMP_READ)
            {
                remove_mission(ms);
            }
            else
            {
                ms->ready();
            }
        }
        else
        {
            if(!m_online)
            {
                int ver=((m_connect_test_mission->get_recv_buffer()[3]&0xff)<<8)
                        +((m_connect_test_mission->get_recv_buffer()[4]&0xff));
                emit online();
                emit machine_version(ver);
                m_online=true;
            }
        }


    }
}

void QMissionManager::reset()
{
    foreach(QMission* ms,m_pause_list)
    {
        ms->set_attribute(MISSION_STATUS,MS_READY);
        ms->set_attribute(MISSION_RETRIES,RETRY_TIMES);
        m_missions.append(ms);
    }
    m_pause_list.clear();
}

void QMissionManager::pause(const QStringList &list)
{
    QString id;
    if(list.size()>0)
    {
        foreach(QMission* ms,m_missions)
        {
            id=ms->get_attribute(MISSION_UUID).toString();
            if(list.contains(id))
            {
                if(ms->get_attribute(MISSION_TYPE).toInt()<=MT_TEMP_READ)
                {
                    remove_mission(id);
                }
                else
                {
                    ms->set_attribute(MISSION_STATUS,MS_PAUSE);
                    ms->set_attribute(MISSION_RETRIES,RETRY_TIMES);
                    m_missions.removeAll(ms);
                    m_pause_list.append(ms);
                }
            }
        }
    }
    else
    {
        foreach(QMission* ms,m_missions)
        {
            id=ms->get_attribute(MISSION_UUID).toString();
            if(ms->get_attribute(MISSION_TYPE).toInt()<=MT_TEMP_READ)
            {
                remove_mission(id);
            }
            else
            {
                ms->set_attribute(MISSION_STATUS,MS_PAUSE);
                ms->set_attribute(MISSION_RETRIES,RETRY_TIMES);
                m_missions.removeAll(ms);
                m_pause_list.append(ms);
            }
        }
    }
}

void QMissionManager::add_mission_group(const QList<QMission *> list,const QString &name)
{
    emit mission_group_start(list.size());
    foreach(QMission* ms,list)
    {
        add_mission(ms);
        m_mission_group.append(m_id_to_mission.value(ms->get_attribute(MISSION_UUID).toString()));
    }

    m_mission_group_name=name;
}

QString QMissionManager::group_mission_name()
{
    return m_mission_group_name;
}

void QMissionManager::set_connect_mission(QMission *ms)
{
    if(m_connect_test_mission!=NULL)
    {
        delete m_connect_test_mission;
    }
    m_connect_test_mission=ms;
    if(m_connect_test_mission!=NULL)
    {
        ms->set_attribute(MISSION_STATUS,MS_RETRY);
    }
}
